package cron.core.loader;

import cron.core.ResourceLoadType;
import cron.core.ResourceTaskScheduler;
import cron.core.ResourceType;
import cron.task.plugin.Task;

import java.io.IOException;
import java.net.*;

/**
 * 通过URL加载jar
 * @author : willian fu
 * @version : 1.0
 * @date : 2021/2/25 0025 13:16
 */
public class JarResourceLoader extends URLClassLoader
        implements ResourceLoader, TaskLoader{

    private JarURLConnection jarURLConnection;

    public JarResourceLoader(URL url) throws IOException {
        super(new URL[] {url}, getParentClassLoader());
    }

    public JarResourceLoader(String path, ResourceLoadType type) throws IOException {
        this(new URL(type.getLoadURL(path)));
    }

    /**
     * 定位基于当前上下文的父类加载器
     * @return 返回可用的父类加载器.
     */
    private static ClassLoader getParentClassLoader() {
        ClassLoader parent = JarResourceLoader.class.getClassLoader();
        return null == parent ? ClassLoader.getSystemClassLoader() : parent;
    }

    /**
     * 加载资源
     */
    @Override
    public void load() throws IOException {
        URL url = this.getURLs()[0];
        addURL(url);
        ResourceTaskScheduler.CLASS_LOADERS.put(url.getFile(), this);
        URLConnection uc = url.openConnection();
        if (uc instanceof JarURLConnection) {
            uc.setUseCaches(true);
            jarURLConnection = (JarURLConnection) uc;
            jarURLConnection.getManifest();
            ResourceTaskScheduler.URL_CONNECTS.put(url.getFile(), jarURLConnection);
        }
    }

    /**
     * 卸载资源
     */
    @Override
    public void unload() throws IOException {
        if (null != jarURLConnection){
            jarURLConnection.getJarFile().close();
            jarURLConnection = null;
            System.gc();
        }
        ResourceTaskScheduler.URL_CONNECTS.remove(this.getURLs()[0].getFile());
    }

    @Override
    public Task[] loadTaskInstance(String ...clazz)
            throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Task[] tasks = new Task[clazz.length];
        int i = 0;
        for (Class<? extends Task> task : loadClazzs(clazz)) {
            //创建任务实例对象
            tasks[i] = task.newInstance();
            i++;
        }
        return tasks;
    }

    @Override
    public Class<? extends Task>[] loadClazzs(String ...clazz)
            throws ClassNotFoundException {
        Class<? extends Task>[] classes = new Class[clazz.length];
        int i = 0;
        for (String name : clazz) {
            classes[i] = (Class<? extends Task>) loadClass(name);
            i++;
        }
        return classes;
    }
}
